Screen=function(host){
  this.host=host;

  this.addWindow=function(name){
    var div=document.createElement('div');
    
    var winName=document.createElement('div'); //Hidden DIV for storing window name since attributes don't support all characters.
    winName.innerText=name;
    var winNameStyle=document.createAttribute("class");
    winNameStyle.nodeValue='hidden';
    winName.setAttributeNode(winNameStyle);
    
    var winContent=document.createElement('div'); //Actual content goes here.
    var winContentStyle=document.createAttribute("class");
    winContentStyle.nodeValue='winContentS';
    winContent.setAttributeNode(winContentStyle);

    div.appendChild(winName);
    div.appendChild(winContent);
    this.host.appendChild(div);
    //TODO: Call code to update treeview/switchbar etc.
  }
  
  this.findWindow=function(winName){
    var divs=this.host.childNodes;
    for (var i=0;i<divs.length;i++){
      if(divs[i].firstChild.innerText.toLowerCaseIRC()==winName.toLowerCaseIRC()) {
        return divs[i].lastChild;
      }
    }
	  return null;
  }
  
  this.addLine=function(winName,text){
    //TODO: Make sure window exists, else echo to status (and include window name)
    //We need a proper echo function (soon)
    var div=document.createElement('div');
    div.innerHTML=colorCode(text.escapeHTML())+"<br>";
    mScreen.findWindow(winName).appendChild(div);
  }
}

function colorCode(x,fo,bo){
  var b=0, u=0, r=0, fo=fo||1, bo=bo||0, fg=fo, bg=bo, z;
  this.ss=function(x,y){
    var g="", z="";
    if (!x){
      z="</span>";
    }
    if (b){
      g+="font-weight:bold;";
    }
    if (u){
      g+="text-decoration:underline;";
    }
    if (fg!=fo||y==2||r) {
      g+="color:"+mirc2js((r)?bo:fg)+";";
    }
    if (bg!=bo||y==2||r) {
      g+="background-color:"+mirc2js((r)?fo:bg)+";";
    }
    return z+"<span"+((g)?" style=\""+g+"\"":"")+">";
  }
  z=this.ss(2);
  z+=this.ss(1);
  for (i = 0; i <= x.length; i++) {
    switch (x.charCodeAt(i)) {
      case 2:
        b=(b)?0:1;
        z+=this.ss("b");
        break;
      case 3:
        co=regx=x.substring(i+1).match(/^((\d{1,2})(?:,(\d{1,2}))?)/);
        if (co) {
          i=i+co[1].length;
          fg=(co[2]>15)?fo:co[2];
          if (co[3]) {
            bg=(co[3]>15)?bo:co[3];
          }
        }
        else {
          fg=fo;
          bg=bo;
        }
        z+=this.ss();
        break;
      case 15:
        b=0, r=0, u=0, fg=fo, bg=bo;
        z+=this.ss();
        break;
      case 22:
        r=(r)?0:1;
        z+=this.ss();
        break;
      case 31:
        u=(u)?0:1;
        z+=this.ss();
        break;
      default:
        z+=x.charAt(i);
        break;
    }
  }
  z+="</span></span>";
  return z;
}

String.prototype.toLowerCaseIRC=function(){return this.replace("\\","|").replace("[","{").replace("]","}").toLowerCase();}
String.prototype.toUpperCaseIRC=function(){return this.replace("|","\\").replace("{","[").replace("}","]").toUpperCase();}

String.prototype.escapeHTML=function(){
  var div = document.createElement('div');
   var text = document.createTextNode(this);
   div.appendChild(text);
   return div.innerHTML;
}
mScreen=new Screen(document.getElementById('mHost'));
mScreen.addWindow('Status');
mScreen.addWindow('@Debug');

//-Socket connection-\\
var socket = new Orbited.TCPSocket();
socket.onopen = function() {
  addDebug("-x- Connected to server.");
  ircSocket_write("USER Webchat * * :Testing new webchat.");
  ircSocket_write("NICK JD[Test]");
}

socket.onread = function(message) {
  var msgs = message.split("\r\n");
  for (var i=0; i< msgs.length; i++)
  ircSocket_read(msgs[i]);
}

socket.onclose = function(code) {
  switch(code) {
    case Orbited.Errors.ConnectionTimeout:
      addDebug("-x- Disconnected: Connection Timeout");
      break;
    case Orbited.Errors.InvalidHandshake:
      addDebug("-x- Disconnected: Invalid Handshake");
      break;
    case Orbited.Errors.UserConnectionReset:
      addDebug("-x- Disconnected: User Connection Reset");
      break;
    case Orbited.Errors.Unauthorized:
      addDebug("-x- Disconnected: Unauthorized Connection");
      break;
    case Orbited.Errors.RemoteConnectionFailed:
      addDebug("-x- Disconnected: Remote Connection Failed");
      break;
    case Orbited.Statuses.ServerClosedConnection:
      addDebug("-x- Disconnected: Server Closed Connection");
      break;
    case Orbited.Statuses.SocketControlKilled:
      addDebug("-x- Disconnected: Socket Control Killed");
      break;
  }
}
socket.open("localhost", 6667);

function ircSocket_write(message){
  addDebug("--> "+message);
  socket.send(message+"\r\n");
}

function ircSocket_read(data){
  if (data) {
    addDebug('<-- '+data);
    if (m___gettok(data,1,32) == "PING") {
      ircSocket_write("PONG "+m___gettok(data,"2-",32))
    }
    else {
      switch(m___gettok(data,2,32)) {
        case "001":
          mScreen.addLine('Status',"Connected as "+m___gettok(data,3,32));
          ircSocket_write("JOIN #Test");
          break;
      }
    }
  }
}

function addDebug(text) {
  //console.log(text);
  mScreen.addLine('@Debug', text);
}

function throwErr(errorx) {
  throw new Error(errorx);
}

function mirc2js(color) {
  switch (parseInt(color,10)) { //Convert string to number
    case 0:
      return "#ffffff";
    case 1:
      return "#000000";
    case 2:
      return "#00007f";
    case 3:
      return "#009300";
    case 4:
      return "#ff0000";
    case 5:
      return "#7f0000";
    case 6:
      return "#9c009c";
    case 7:
      return "#fc7f00";
    case 8:
      return "#ffff00";
    case 9:
      return "#00fc00";
    case 10:
      return "#009393";
    case 11:
      return "#00ffff";
    case 12:
      return "#0000fc";
    case 13:
      return "#ff00ff";
    case 14:
      return "#7f7f7f";
    case 15:
      return "#d2d2d2";
    default:
      return 0;
  }
}

String.prototype.mSplit=function(delim){ //TODO: Fix delim, Only works on ASCII 32?
  var delim=delim || 32;
  if (isNaN(delim)) {
    throwErr("ERR_PARAMNOTVALID");
  }
  var text=this+"x", retArray=new Array();
  for (var i=0, j=0, a=0, len=text.length; i<len; ++i){
    if (text.charCodeAt(i) == delim || i==len-1){
      if (text.substring(j,i).replace(String.fromCharCode(delim),'')){
        ++a;
        retArray[a]=text.substring(j,i);
      }
      j=i+1;
    }
  }
  retArray[0]=retArray.length-1;
  return retArray;
}

//- mIRC-like commands
function m___asc(c){
  return c.charCodeAt(0)
}

function m___ceil(n){
  return Math.ceil(n);
}

function m___chr(n){
  return String.fromCharCode(n);
}

function m___cr(){
  return "\r";
}

function m___crlf(){
  return "\r\n";
}

function m___ctime(text) {
  if (!text) {
    return Math.floor(new Date().getTime()/1000);
  }
  else {
    return null; //We need to interpret the date.
  }
}

function m___floor(n){
  return Math.floor(n);
}

function m___gettok(text,n,c){
  if (!c || isNaN(c)) {
    throwErr("m___gettok: Invalid Param (c)");
  }
  var text=text.mSplit(c), na=new Array(), regx=new Array();
  n+="";
  regx=n.match(/^([0-9]+)(?:(-)([0-9]+)?)?$/);
  if (!regx[1]) {
    throwErr("m___gettok: Invalid Param (n)");
  }
  else if (regx[1]==0) {
    return text[0];
  }
  if (!regx[3] && regx[2]) {
    regx[3]=text[0];
  }
  else if (!regx[2]) {
    regx[3]=regx[1]
  }
  for (var i=1; i<text.length; ++i){ //Consider array.slice(start, end);
    if (i>=regx[1] && i<=regx[3]) {
      na.push(text[i])
    }
  }
  return na.join(String.fromCharCode(c));
}

function m___left(text,n){
  return text.substring(0,n); //TODO: Add negative values ($left(text,-n)).
}

function m___lf(){
  return "\n";
}

function m___len(text){
  return text.length;
}

function m___mid(text,s,n){
  return text.substring(s-1,s-1+n);
}

function m___null(){
  return null;
}

function m___os(){
  return "Web";
}

function m___pi(){
  return 3.14159265358979323846;
}

function m___right(text,n){
  return text.substring(text.length-n,text.length); //TODO: Add negative values ($left(text,-n)).
}

function m___timestamp(){
  //TODO: Make timestamp generate according to m___timestampfmt() return
  var curTime = new Date();
  var curHour = curTime.getHours();
  var curMin = curTime.getMinutes();
  if (curHour < 10) {
    curHour = "0" + curHour;
  }
  if (curMin < 10) {
    curMin = "0" + curMin;
  }
  return "[" + curHour + ":" + curMin + "]";
}

function m___timestampfmt() {
  return "[HH:nn]";
}

function m___version(){
  return "0.53";
}